using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Web;
using System.ComponentModel;
using System.Web.Script.Serialization;
using System.Web.UI.HtmlControls;

[assembly: WebResource("DynamicExcelImportWebControl.MiniLightbox.js", "text/javascript")]
[assembly: WebResource("DynamicExcelImportWebControl.MiniLightbox.css", "text/css")]
[assembly: WebResource("DynamicExcelImportWebControl.ExcelImport.js", "text/javascript")]
[assembly: WebResource("DynamicExcelImportWebControl.ExcelImportEventHandlers.js", "text/css")]
namespace DynamicExcelImportWebControl
{
    [DefaultProperty("Columns"), ParseChildren(true, "Columns")]
    public class ExcelImportControl : WebControl, IPostBackDataHandler, INamingContainer
    {
        private static readonly object EventSubmit = new object();

        public string[][] TableData { get; set; }

        private Button submitButton;

        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public List<BaseGridColumn> Columns { get; set; }

        #region [ Submit Event ]

        public class ExcelImportControlSubmitEventArgs : EventArgs
        {
            public string[][] Data { get; set; }
        }
        public delegate void ExcelImportControlSubmitEventHandler(object sender, ExcelImportControlSubmitEventArgs e);
        public event ExcelImportControlSubmitEventHandler Submit
        {
            add { base.Events.AddHandler(EventSubmit, value); }
            remove { base.Events.RemoveHandler(EventSubmit, value); }
        }

        protected virtual void OnSubmit(ExcelImportControlSubmitEventArgs e)
        {
            ExcelImportControlSubmitEventHandler handler = (ExcelImportControlSubmitEventHandler)base.Events[EventSubmit];
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        public ExcelImportControl()
        {
            TableData = null;

            this.Columns = new List<BaseGridColumn>();
            submitButton = new Button();
        }

        protected override void OnPreRender(EventArgs e)
        {
            //Register the minilightbox script file
            string scriptPath = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "DynamicExcelImportWebControl.MiniLightbox.js");
            this.Page.ClientScript.RegisterClientScriptInclude("MiniLightbox", scriptPath);

            //Register style sheet
            string cssUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "DynamicExcelImportWebControl.MiniLightbox.css");
            HtmlLink cssLink = new HtmlLink();
            cssLink.Href = cssUrl;
            cssLink.Attributes.Add("rel", "stylesheet");
            cssLink.Attributes.Add("type", "text/css");
            this.Page.Header.Controls.Add(cssLink);

            //Register the ImportGrid Javascript file (from embedded resource)
            scriptPath = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "DynamicExcelImportWebControl.ExcelImport.js");
            this.Page.ClientScript.RegisterClientScriptInclude("DynamicExcelImportWebControl", scriptPath);

            //Register the event handlers for the Paste event (from embedded resource)
            scriptPath = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "DynamicExcelImportWebControl.ExcelImportEventHandlers.js");
            this.Page.ClientScript.RegisterClientScriptInclude("DynamicExcelImportWebControlEventHandlers", scriptPath);

            base.OnPreRender(e);
        }

        #region [ Helper Functions ]
        //Duplicate of the GetPostBackEventReference in Page.ClientScript, except it does not escape the argument string
        //It is mildly irritating that I must hack this together.
        public string GetPostBackEventReference(Control control, string argument, bool registerForEventValidation)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }
            string uniqueID = control.UniqueID;
            if (registerForEventValidation)
            {
                this.Page.ClientScript.RegisterForEventValidation(uniqueID, argument);
            }
            if ((uniqueID != null) && (uniqueID.IndexOf(':') >= 0))
            {
                uniqueID = uniqueID.Replace(':', '$');
            }
            return (("__doPostBack('" + uniqueID + "',") + argument + ")");
        }
        #endregion

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            //Lightbox Panel
            Panel lightbox = new Panel();
            lightbox.ID = this.ClientID + "_LightboxContainer";
            lightbox.CssClass = "lightboxcontent";

            //Grid Container Panel
            Panel gridContainer = new Panel();
            gridContainer.ID = this.ClientID + "_TargetGridContainer";

            lightbox.Controls.Add(gridContainer);

            #region [ Grid Init Script ]

            StringBuilder sb = new StringBuilder();
            string targetGridJsId = this.ClientID + "_TargetGrid";
            sb.AppendFormat("var {0} = null;", targetGridJsId);
            sb.AppendLine();
            sb.AppendLine("if(document.getElementById('" + gridContainer.ClientID + "') != null){");
            sb.AppendFormat("{0} = new ImportGrid(document.getElementById('{1}'));", targetGridJsId, gridContainer.ClientID);
            sb.AppendLine();
            foreach (BaseGridColumn var in this.Columns)
            {
                sb.AppendLine(
                    var.RenderInitScript(targetGridJsId + ".AddColumn({0});")
                    );
            }
            sb.AppendLine("}");
            this.Page.ClientScript.RegisterStartupScript(this.GetType(), "TargetGridStartup", sb.ToString(), true);

            #endregion

            #region [ Popup Init Script ]

            string miniLightboxOverlayId = this.ClientID + "_MiniLightboxOverlay";

            writer.AddAttribute(HtmlTextWriterAttribute.Id, miniLightboxOverlayId);
            writer.AddAttribute(HtmlTextWriterAttribute.Class, "lightboxoverlay");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.RenderEndTag();

            sb = new StringBuilder();
            string popupObjectId = this.ClientID + "_MiniLightbox";
            sb.AppendFormat("var {0} = new MiniLightbox('{1}', '{2}');", popupObjectId, lightbox.ClientID, miniLightboxOverlayId);
            sb.AppendLine();
            this.Page.ClientScript.RegisterStartupScript(this.GetType(), "MiniLightboxStartup", sb.ToString(), true);

            #endregion

            //Paste Target
            System.Web.UI.HtmlControls.HtmlTextArea t = new System.Web.UI.HtmlControls.HtmlTextArea();
            t.ID = this.ClientID + "_PasteTarget";
            t.Attributes.Add("oninput", "EI_ffPasteHandler(this, " + targetGridJsId + ", " + popupObjectId + ")");
            t.Attributes.Add("onpaste", "EI_iePasteHandler(" + targetGridJsId + ", " + popupObjectId + ")");
            t.Attributes.Add("ondrop", "EI_ieDropHandler(" + targetGridJsId + ", " + popupObjectId + ")");
            t.RenderControl(writer);

            //Cancel Button
            HtmlInputButton cancelButton = new HtmlInputButton();
            cancelButton.Value = "Cancel";
            cancelButton.ID = this.ClientID + "_cancel";
            cancelButton.Name = this.ClientID + "_cancel";
            cancelButton.Attributes.Add("onclick", popupObjectId + ".deactivate(); return false;");
            cancelButton.Style.Add("margin", "5px");
            cancelButton.Style.Add("float", "right");

            //Submit Button
            string postBackString = this.GetPostBackEventReference(submitButton, targetGridJsId + ".Serialize()", true);
            submitButton.Text = "Submit";
            submitButton.ID = this.UniqueID;
            submitButton.OnClientClick = postBackString;
            submitButton.Style.Add("margin", "5px");
            submitButton.Style.Add("float", "right");

            //Button Holder
            Panel buttonHolder = new Panel();
            buttonHolder.Style.Add(HtmlTextWriterStyle.Position, "absolute");
            buttonHolder.Style.Add("bottom", "0px");
            buttonHolder.Style.Add("right", "0px");
            lightbox.Controls.Add(buttonHolder);

            //Order is important
            buttonHolder.Controls.Add(cancelButton);
            buttonHolder.Controls.Add(submitButton);

            //Render Container Panel
            lightbox.RenderControl(writer);
        }

        #region IPostBackDataHandler Members

        bool IPostBackDataHandler.LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
        {
            if (!string.IsNullOrEmpty(postCollection["__EVENTARGUMENT"]))
            {
                string postedValue = postCollection["__EVENTARGUMENT"].Trim();
                if (postedValue.Length > 0)
                {
                    try
                    {
                        JavaScriptSerializer s = new JavaScriptSerializer();
                        TableData = s.Deserialize<string[][]>(postedValue);
                    }
                    catch
                    {
                    }
                    return true;
                }
            }

            return false;
        }

        void IPostBackDataHandler.RaisePostDataChangedEvent()
        {
            this.OnSubmit(new ExcelImportControlSubmitEventArgs { Data = this.TableData });
        }

        #endregion
    }

}
